package com.opennews.openplatform.familyexpenseapi.controller

import com.opennews.openplatform.familyexpenseapi.dto.income.expense.detail.IncomeExpenseDetailQueryArgument
import com.opennews.openplatform.familyexpenseapi.dto.journey.income.expense.detail.CreateJourneyIncomeExpenseDetailDto
import com.opennews.openplatform.familyexpenseapi.dto.journey.income.expense.detail.UpdateJourneyIncomeExpenseDetailDto
import com.opennews.openplatform.familyexpenseapi.service.JourneyIncomeExpenseDetailService
import com.opennews.openplatform.myspringbootcore.dto.ApiResponse
import com.opennews.openplatform.myspringbootcore.dto.IdentityDto
import com.opennews.openplatform.myspringbootcore.util.getSuccessResponse
import com.opennews.openplatform.myspringbootmvccore.security.RequestIdentityExtractor
import jakarta.validation.Valid
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/journey-income-expense-detail")
class JourneyIncomeExpenseDetailController(
    private val journeyIncomeExpenseDetailService: JourneyIncomeExpenseDetailService,
    private val requestIdentityExtractor: RequestIdentityExtractor,
) {
    @GetMapping("/query-existing-distinct-years")
    fun queryExistingDistinctYears(): ResponseEntity<ApiResponse<List<Int>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        val result = journeyIncomeExpenseDetailService.queryExistingDistinctYears(accountGroupId)

        return getSuccessResponse(result)
    }

    @GetMapping("/query-list-by-journey")
    fun queryListByJourney(
        @RequestParam journeyId: String,
        @RequestParam keyword: String,
        @RequestParam pageSize: Int,
        @RequestParam pageIndex: Int,
    ): ResponseEntity<ApiResponse<List<Map<String, Any>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()

        // Prepares the query argument
        val queryArgument = IncomeExpenseDetailQueryArgument().apply {
            this.accountGroupId = accountGroupId
            this.keyword = keyword
            this.pageSize = pageSize
            this.pageIndex = pageIndex
        }

        val result = journeyIncomeExpenseDetailService.queryListByJourney(journeyId, queryArgument)
        return getSuccessResponse(result)
    }

    @GetMapping("/query-details")
    fun queryDetails(@RequestParam id: String): ResponseEntity<ApiResponse<Map<String, Any>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        val result = journeyIncomeExpenseDetailService.queryDetails(accountGroupId, id)

        return getSuccessResponse(result)
    }

    @GetMapping("/query-coordinates")
    fun queryCoordinates(@RequestParam year: String): ResponseEntity<ApiResponse<List<Map<String, Any>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        val result = journeyIncomeExpenseDetailService.queryCoordinates(accountGroupId, year)

        return getSuccessResponse(result)
    }

    @PostMapping("/add")
    fun add(@Valid @RequestBody data: CreateJourneyIncomeExpenseDetailDto): ResponseEntity<ApiResponse<Any?>> {
        val claims = requestIdentityExtractor.getClaims()
        journeyIncomeExpenseDetailService.add(claims.accountGroupId.asString(), claims.username, data)

        return getSuccessResponse()
    }

    @PostMapping("/update")
    fun update(@Valid @RequestBody data: UpdateJourneyIncomeExpenseDetailDto): ResponseEntity<ApiResponse<Any?>> {
        val claims = requestIdentityExtractor.getClaims()
        journeyIncomeExpenseDetailService.update(claims.accountGroupId.asString(), claims.username, data)

        return getSuccessResponse()
    }

    @PostMapping("/delete")
    fun delete(@Valid @RequestBody data: IdentityDto): ResponseEntity<ApiResponse<Any?>> {
        val id = data.id.asString()
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        journeyIncomeExpenseDetailService.delete(accountGroupId, listOf(id))

        return getSuccessResponse()
    }
}